// src/websocket/websocket.js
const WebSocket = require('ws');
const pako = require('pako')
const moment = require("moment");
const path = require('path');
const fs = require('fs');

const targetDir = path.join(__dirname, '../static_excel_json');
if (!fs.existsSync(targetDir)) {
  fs.mkdirSync(targetDir, { recursive: true });
}

function unzip (str) {
  let chartData = str
    .toString()
    .split("")
    .map((i) => i.charCodeAt(0));
 
  let binData = new Uint8Array(chartData);
  let data = ''
  try {
    data = pako.inflate(binData);
  } catch (error) {
    
  }
  return decodeURIComponent(
    String.fromCharCode.apply(null, new Uint16Array(data))
  )
}

function callbackdata(user, data, type) {
  /**
   * createTime: 命令发送时间
   * data:{} 修改的命令
   * id: "7a"   websocket的id
   * returnMessage: "success"
   * status: "0"  0告诉前端需要根据data的命令修改  1无意义
   * type: 0：连接成功，1：发送给当前连接的用户，2：发送信息给其他用户，3：发送选区位置信息，999：用户连接断开
   * username: 用户名
   *
   * 源码中的数据解释：
   */
  return JSON.stringify({
    createTime: moment().format("YYYY-MM-DD HH:mm:ss"),
    data,
    id: user.id,
    returnMessage: "success",
    status: 0,
    type,
    username: user.name,
  });
}
/**
 * ws 事件响应中心
 *  根据不同的事件，返回不同的数据
 *  type 1 成功/失败
 *  type 2 更新数据
 *  type 3 用户光标
 *  type 4 批量处理数据
 */
function wshandle(user, data) {
  // 表示用户移动鼠标 实际是需要根据指令实现不同的响应的，但是这里统一做 更新数据
  this.send(callbackdata(user, data, JSON.parse(data).t === "mv" ? 3 : 2));
}
// 处理sheet页
function setSheet (fileId, data) {
  const filePath = path.join(targetDir, `${fileId}.json`);
  const fileContent = fs.readFileSync(filePath, 'utf-8');
  const jsonData = JSON.parse(fileContent);
  if (data.t === 'sha') { // 新增SHEET
    jsonData.sheets.push(data.v);
    // console.log(filePath, jsonData);
    fs.writeFileSync(filePath, JSON.stringify(jsonData, null, 2), { flag: 'w' });
    console.log('sheet页更新成功')
    return false
  } else if (data.t === 'shd') { // 删除SHEET
    const deleIndex = data.v.deleIndex
    const index = jsonData.sheets.findIndex(item => item.index === deleIndex)
    jsonData.sheets.splice(index, 1)
    fs.writeFileSync(filePath, JSON.stringify(jsonData, null, 2), { flag: 'w' });
    console.log('sheet页更新成功')
    return false
  } else if (data.t === 'shr') { // 移动SHEET

  }
 
}

function setupWebSocket(server) {
  const wss = new WebSocket.Server({ server });

  wss.on('connection', (ws, req) => {
    console.log('新的WebSocket连接已建立');
    console.log(req.url);
    const userId = new URL(req.url, 'http://xxx.com').searchParams.get('userId');
    const userName = new URL(req.url, 'http://xxx.com').searchParams.get('userName');
    const fileId = new URL(req.url, 'http://xxx.com').searchParams.get('fileId');
     console.log(userName);
    // let id = Math.random().toString().split(".")[1].slice(0, 3);
    ws.wid = userId;
    ws.wname = userName;
    ws.fileid = fileId;
    // 发送欢迎消息
    // ws.send(JSON.stringify({
    //   type: 'welcome',
    //   message: '欢迎连接到WebSocket服务器!',
    //   timestamp: new Date().toISOString()
    // }));

    // 处理消息
    ws.on('message', (data) => {
      if (data !== 'rub') {
        // const ungzipped = pako.ungzip(message, { to: 'string' })
        console.log(`收到消息: ${unzip(data)}`);
        setSheet(fileId, JSON.parse(unzip(data)))
        
        // 广播消息
        wss.clients.forEach((conn) => {
          if (conn.fileid !== ws.fileid) return; // 如果与我当前操作文件不一致，则不发送消息给你
          if (conn.wid === ws.wid) return;
          // 使得 this 指向当前连接对象 ,并且保证，操作对象始终是当前用户
        try {
          wshandle.call(conn, { id: ws.wid, name: ws.wname }, unzip(data));
        } catch (error) {
          
        }
        });
      }
    });

    ws.on('close', () => {
      console.log('WebSocket连接已关闭');
    });
  });

  // 定时发送服务器时间
  // setInterval(() => {
  //   wss.clients.forEach((client) => {
  //     if (client.readyState === WebSocket.OPEN) {
  //       client.send(JSON.stringify({
  //         type: 'serverTime',
  //         time: new Date().toISOString()
  //       }));
  //     }
  //   });
  // }, 5000);

  return wss;
}

module.exports = setupWebSocket;